import { useEffect, useRef, useState, useCallback } from "react";
import { Select, Input, Button, Radio } from "antd";
import { cloneDeep, find, remove, findIndex } from "lodash";
import classNames from "classnames";
import QRCode from "qrcode.react";
import IconFont from "@/components/IconFont";
import CommonImgsLoad from "@/components/CommonImgsLoad";
import BarCode from "./BarCode";
import styles from "./index.module.less";

const { Option } = Select;

const goodsInfoMap = {
	goodsName: "订单商品名称",
	goodsSpce: "订单规格属性",
	spuId: "订单款式编码",
	goodsId: "订单商品编码"
};

//用于拖拽的几个点,右上角的拖拽用删除替代,东南西北， 删除、西北、东南、西南
const points = ["E", "W", "S", "N", "D", "NW", "SE", "SW"];

const pointsCode = ["D", "NW", "SE", "SW"];

const textFamily = [
	"宋体",
	"黑体",
	"微软雅黑",
	"Arial",
	"Times New Roman",
	"Tahoma",
	"wedbings",
	"Arial Black",
	"Arial Narrow",
	"Arial Unicode MS"
];

const textSize = [7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 40, 50, 60, 70, 80, 90, 100];

const TemplateLeft = ({ currId, attrList, sizeScale, templateData, updateData, updateId }) => {
	const { totalWidth = 50, totalHeight = 80, templateValue = [] } = templateData;

	const widthPx = totalWidth * sizeScale,
		heightPx = totalHeight * sizeScale;

	//控制鼠标是否按下
	const isDown = useRef(false);

	//方向控制
	const direction = useRef(null);

	//初始数据，不需要重新render，是用useRef；
	const oriPos = useRef({
		top: 0,
		left: 0,
		cX: 0,
		cY: 0
	});

	useEffect(() => {
		if (currId) {
			const obj = find(templateValue, ["id", currId]);
			setStyle(obj);
		}
	}, [currId]);

	//初始化样式
	const [style, setStyle] = useState({});

	//鼠标被按下
	const onMouseDown = (dir, e) => {
		// 阻止事件冒泡
		e.stopPropagation();

		// 保存方向。
		direction.current = dir;
		isDown.current = true;

		// 然后鼠标坐标是
		const cY = e.clientY; // clientX 相对于可视化区域
		const cX = e.clientX;
		oriPos.current = {
			...style,
			cX,
			cY
		};
	};

	//鼠标移动
	const onMouseMove = e => {
		// 判断鼠标是否按住
		if (!isDown.current) {
			return;
		}
		const newStyle = transform(direction, oriPos, e);
		setStyle(newStyle);
	};

	//鼠标被抬起
	const onMouseUp = e => {
		if (isDown.current) {
			isDown.current = false;
			//鼠标抬起的时候进行赋值
			const obj = cloneDeep(templateData);
			const arr = obj.templateValue;
			const obj1 = find(arr, ["id", currId]);
			if (obj1) {
				obj1.left = style.left;
				obj1.top = style.top;
				obj1.width = style.width;
				obj1.height = style.height;
				updateData(obj);
			}
		}
	};

	/**
	 * 元素变化。 方法放在组件外部或者其他地方。
	 * @param direction  方向 // move 移动 / 'e', 'w', 's', 'n', 'ne', 'nw', 'se', 'sw'
	 * @param oriPos  鼠标按下时所记录的坐标
	 * @param e        事件event
	 */
	const transform = (direction, oriPos, e) => {
		const style = { ...oriPos.current };
		const offsetX = e.clientX - oriPos.current.cX;
		const offsetY = e.clientY - oriPos.current.cY;

		switch (direction.current) {
			// 拖拽移动
			case "move":
				// 元素当前位置 + 偏移量
				const top = oriPos.current.top + offsetY;
				const left = oriPos.current.left + offsetX;
				// 限制必须在这个范围内移动 画板的高度-元素的高度
				style.top = Math.max(0, Math.min(top, heightPx - style.height));
				style.left = Math.max(0, Math.min(left, widthPx - style.width));
				break;

			// 东
			case "E":
				// 向右拖拽添加宽度
				style.width += offsetX;
				break;

			// 西
			case "W":
				// 增加宽度、位置同步左移
				style.width -= offsetX;
				style.left += offsetX;
				break;

			// 南
			case "S":
				style.height += offsetY;
				break;

			// 北
			case "N":
				style.height -= offsetY;
				style.top += offsetY;
				break;

			// 东北
			case "NE":
				style.height -= offsetY;
				style.top += offsetY;
				style.width += offsetX;
				break;

			// 西北
			case "NW":
				style.height -= offsetY;
				style.top += offsetY;
				style.width -= offsetX;
				style.left += offsetX;
				break;

			// 东南
			case "SE":
				style.height += offsetY;
				style.width += offsetX;
				break;

			// 西南
			case "SW":
				style.height += offsetY;
				style.width -= offsetX;
				style.left += offsetX;
				break;
		}

		//手动限制一下范围
		const { left, top, height, width } = style;
		if (width + left > widthPx) {
			style.left = widthPx - width;
		}
		if (left < 0) {
			style.left = 0;
		}
		if (top + height > heightPx) {
			style.top = heightPx - height;
		}
		if (top < 0) {
			style.top = 0;
		}

		//二维码宽高保持一致
		const obj = find(templateValue, ["id", currId]);
		if (obj.type == "qrcode") {
			style.width = style.height;
		}
		return style;
	};

	//文本框输入后 update
	const handleTextChange = (e, id) => {
		const obj = cloneDeep(templateData);
		const arr = obj.templateValue;
		const obj1 = find(arr, ["id", id]);
		obj1.value = e.target.value;
		updateData(obj);
	};

	//图片上传后 update
	const handleUploadImg = (value, id) => {
		const obj = cloneDeep(templateData);
		const arr = obj.templateValue;
		const obj1 = find(arr, ["id", id]);
		obj1.value = value;
		updateData(obj);
	};

	//点击选中需要操作的数据框
	const handleSelect = (e, id) => {
		e.stopPropagation();
		if (id == currId) {
			return;
		} else {
			updateId(id);
		}
	};

	//点击样式事件
	const handleChangeStyle = (val, type) => {
		const obj1 = cloneDeep(templateData);
		const arr = obj1.templateValue;
		const obj = find(arr, ["id", currId]);
		if (obj[type]) {
			if (obj[type] == val) {
				delete obj[type];
			} else {
				obj[type] = val;
			}
		} else {
			obj[type] = val;
		}
		updateData(obj1);
		setStyle(obj);
	};

	//删除数据
	const handleDeleteData = id => {
		const obj = cloneDeep(templateData);
		const arr = obj.templateValue;
		remove(arr, v => v.id == id);
		updateId(undefined);
		updateData(obj);
	};

	//单选打印字段选择
	const handleChangeRaido = (e, id) => {
		const obj = cloneDeep(templateData);
		const arr = obj.templateValue;
		const obj1 = find(arr, ["id", id]);
		obj1.value = e.target.value;
		updateData({ ...obj });
	};

	//切换字段显示
	const handleChangeField = (id, type, bool) => {
		const obj = cloneDeep(templateData);
		const arr = obj.templateValue;
		const index = findIndex(arr, ["id", id]);
		if (bool) {
			arr[index].value = "#goodsCode#";
		} else {
			arr[index].value = "http://www.zhaojiafang.com/";
		}
		updateData({
			...obj,
			templateValue: arr
		});
	};

	//渲染工具操作属性栏
	const renderToolContent = v => {
		const { fontFamily, fontSize, fontStyle, fontWeight, textDecoration, textAlign, top, type, id, value } = v;

		const isField = ["#ecSkuId#", "#goodsCode#"].includes(value);

		if (type == "qrcode") {
			return (
				<div className={classNames(styles.operaWrapLeft, styles.operaWrap5)}>
					{isField ? (
						<Radio.Group value={value} onChange={e => handleChangeRaido(e, id)}>
							<Radio value="#goodsCode#">订单商品编码</Radio>
							<Radio value="#ecSkuId#">网店商品编码</Radio>
						</Radio.Group>
					) : (
						<div style={{ display: "flex", alignItems: "center" }}>
							<span>二维码信息：</span>
							<Input style={{ flex: 1 }} onChange={e => handleTextChange(e, id)} value={value} placeholder="请输入二维码信息" />
						</div>
					)}
					<Button onClick={() => handleChangeField(id, type, !isField)} style={{ marginTop: 4 }}>
						切换{isField ? "链接" : "字段"}方式
					</Button>
				</div>
			);
		} else if (type == "barcode") {
			return (
				<div className={classNames(styles.operaWrapLeft, styles.operaWrap3)}>
					<div style={{ display: "flex" }}>
						<span>条形码信息：</span>
						<Input style={{ flex: 1 }} onChange={e => handleTextChange(e, id)} value={value} placeholder={`请输入条形码信息`} />
					</div>
				</div>
			);
		} else if (type != "picture") {
			const commonContent = (
				<>
					<div className={styles.styleWrap}>
						<span>字体：</span>
						<Select
							value={fontFamily}
							style={{ width: "100px", marginRight: "8px" }}
							onChange={val => handleChangeStyle(val, "fontFamily")}
						>
							{textFamily.map(v => (
								<Option key={v} value={v}>
									{v}
								</Option>
							))}
						</Select>
						<span>字号：</span>
						<Select value={fontSize} style={{ width: "60px" }} onChange={val => handleChangeStyle(val, "fontSize")}>
							{textSize.map(v => (
								<Option key={v} value={v}>
									{v}
								</Option>
							))}
						</Select>
					</div>
					<div>
						<span>样式：</span>
						<span
							className={styles.fontOpera}
							onClick={() => handleChangeStyle("bold", "fontWeight")}
							style={{
								marginRight: "12px",
								color: fontWeight == "bold" ? "#0165D5" : "#333"
							}}
						>
							B
						</span>
						<span
							className={styles.fontOpera}
							onClick={() => handleChangeStyle("italic", "fontStyle")}
							style={{
								fontStyle: "italic",
								marginRight: "12px",
								color: fontStyle == "italic" ? "#0165D5" : "#333"
							}}
						>
							I
						</span>
						<span
							className={styles.fontOpera}
							onClick={() => handleChangeStyle("underline", "textDecoration")}
							style={{
								textDecoration: "underline",
								color: textDecoration == "underline" ? "#0165D5" : "#333"
							}}
						>
							U
						</span>
						<span className={styles.fontOpera} onClick={() => handleChangeStyle("left", "textAlign")}>
							<IconFont style={{ color: textAlign == "left" ? "#1065D5" : "#333" }} type="iconleft" />
						</span>
						<span className={styles.fontOpera} onClick={() => handleChangeStyle("center", "textAlign")}>
							<IconFont style={{ color: textAlign == "center" ? "#1065D5" : "#333" }} type="iconcenter" />
						</span>
						<span className={styles.fontOpera} onClick={() => handleChangeStyle("right", "textAlign")}>
							<IconFont style={{ color: textAlign == "right" ? "#1065D5" : "#333" }} type="iconright" />
						</span>
					</div>
				</>
			);
			if (type == "customtext") {
				return (
					<div className={classNames(styles.operaWrapLeft, top < 48 ? styles.operaWrap4 : styles.operaWrap2)}>
						<div
							style={{
								display: "flex",
								marginBottom: "12px",
								position: "static",
								zIndex: 20000
							}}
						>
							<span>文本：</span>
							<Input value={value} onChange={e => handleTextChange(e, id)} placeholder="请输入文本内容" style={{ flex: 1 }} />
						</div>
						{commonContent}
					</div>
				);
			} else if (type == "text") {
				return <div className={classNames(styles.operaWrapLeft, styles.operaWrap1)}>{commonContent}</div>;
			}
		}
	};

	//渲染item 主体部分
	const renderMainMsg = v => {
		const { type, props, prop, value, width, height, id, fontSize } = v;
		if (type == "text") {
			const arr = props && props.map(prop => goodsInfoMap[prop]);
			return (
				<div>
					<div>{arr && arr.join("+")}</div>
					{prop ? (
						<div>
							<div>{prop}</div>
						</div>
					) : (
						""
					)}
				</div>
			);
		} else if (type == "customtext") {
			return value;
		} else if (type == "qrcode") {
			return <QRCode value={value} size={width} fgColor="#000000" />;
		} else if (type == "barcode") {
			return <BarCode value={value} height={height} displayValue={true} />;
		} else if (type == "picture") {
			if (value) {
				return (
					<div
						style={{
							width,
							height,
							background: `url("${value}") center center / cover no-repeat`
						}}
					></div>
				);
			} else {
				return <CommonImgsLoad img={value} handleOk={val => handleUploadImg(val, id)} />;
			}
		}
	};

	const dropPointArr = useCallback(v => {
		if (v.type == "qrcode") {
			return pointsCode;
		} else if (v.type != "picture" || v.value) {
			return points;
		} else {
			return ["D"];
		}
	}, []);

	return (
		<div>
			<div
				style={{
					width: widthPx,
					height: heightPx,
					background: "#fff",
					boxShadow: "0px 0px 10px rgb(79 94 112 / 10%)",
					position: "relative"
				}}
				onMouseMove={onMouseMove}
				onMouseUp={onMouseUp}
			>
				{templateValue.map(v => {
					const { id } = v;
					if (id == currId) {
						const dirArr = dropPointArr(v);
						return (
							<div
								key={id}
								className={styles.dragItem}
								onClick={e => handleSelect(e, id)}
								style={{ ...style, zIndex: 1000, border: "1px solid #0165D5" }}
								onMouseDown={e => onMouseDown("move", e)}
							>
								{renderToolContent(v)}
								<div className={styles.renderMsg}>{renderMainMsg(v)}</div>
								{/* 拖拽点 */}
								{dirArr.map(item => {
									if (item == "D") {
										return (
											<div key={item} onClick={() => handleDeleteData(id)} className={styles.pointsDel}>
												<IconFont className type="iconclose" />
											</div>
										);
									} else {
										return (
											<div
												key={item}
												onMouseDown={e => onMouseDown(item, e)}
												className={classNames(styles.controlPoint, styles[`point${item}`])}
											></div>
										);
									}
								})}
							</div>
						);
					} else {
						return (
							<div key={id} className={styles.dragItem} onClick={e => handleSelect(e, id)} style={{ ...v, cursor: "pointer" }}>
								<div className={styles.renderMsg}>{renderMainMsg(v)}</div>
							</div>
						);
					}
				})}
			</div>
		</div>
	);
};

export default TemplateLeft;
